@@ -36,15 +36,6 @@ body { padding-top: 60px; }
|
||
| 36 | 36 |
@extend .control-group.error; |
| 37 | 37 |
} |
| 38 | 38 |
|
| 39 |
-table.events {
|
|
| 40 |
- .payload {
|
|
| 41 |
- color: #999; |
|
| 42 |
- font-size: 12px; |
|
| 43 |
- //text-align: center; |
|
| 44 |
- font-family: monospace; |
|
| 45 |
- } |
|
| 46 |
-} |
|
| 47 |
- |
|
| 48 | 39 |
.select2 {
|
| 49 | 40 |
float: none !important; |
| 50 | 41 |
margin-left: 0 !important; |
@@ -0,0 +1,31 @@ |
||
| 1 |
+// Sortable table headers |
|
| 2 |
+.table th a.selected {
|
|
| 3 |
+ position: relative; |
|
| 4 |
+ text-decoration: underline; |
|
| 5 |
+ |
|
| 6 |
+ &.asc:after, &.desc:after {
|
|
| 7 |
+ text-decoration: none; |
|
| 8 |
+ position: absolute; |
|
| 9 |
+ top: -5px; |
|
| 10 |
+ right: -12px; |
|
| 11 |
+ font-size: 1.2em; |
|
| 12 |
+ } |
|
| 13 |
+ |
|
| 14 |
+ &.asc:after {
|
|
| 15 |
+ content: '\2193'; |
|
| 16 |
+ } |
|
| 17 |
+ |
|
| 18 |
+ &.desc:after {
|
|
| 19 |
+ content: '\2191'; |
|
| 20 |
+ } |
|
| 21 |
+} |
|
| 22 |
+ |
|
| 23 |
+table.events {
|
|
| 24 |
+ .payload {
|
|
| 25 |
+ color: #999; |
|
| 26 |
+ font-size: 12px; |
|
| 27 |
+ //text-align: center; |
|
| 28 |
+ font-family: monospace; |
|
| 29 |
+ } |
|
| 30 |
+} |
|
| 31 |
+ |
@@ -1,8 +1,11 @@ |
||
| 1 | 1 |
class AgentsController < ApplicationController |
| 2 | 2 |
include DotHelper |
| 3 |
+ include SortableTable |
|
| 3 | 4 |
|
| 4 | 5 |
def index |
| 5 |
- @agents = current_user.agents.page(params[:page]) |
|
| 6 |
+ set_table_sort sorts: %w[name last_check_at last_event_at last_receive_at], default: { name: :asc }
|
|
| 7 |
+ |
|
| 8 |
+ @agents = current_user.agents.preload(:scenarios, :controllers).reorder(table_sort).page(params[:page]) |
|
| 6 | 9 |
|
| 7 | 10 |
respond_to do |format| |
| 8 | 11 |
format.html |
@@ -0,0 +1,53 @@ |
||
| 1 |
+require 'active_support/concern' |
|
| 2 |
+ |
|
| 3 |
+module SortableTable |
|
| 4 |
+ extend ActiveSupport::Concern |
|
| 5 |
+ |
|
| 6 |
+ included do |
|
| 7 |
+ helper SortableTableHelper |
|
| 8 |
+ end |
|
| 9 |
+ |
|
| 10 |
+ protected |
|
| 11 |
+ |
|
| 12 |
+ def table_sort |
|
| 13 |
+ raise("You must call set_table_sort in any action using table_sort.") unless @table_sort_info.present?
|
|
| 14 |
+ @table_sort_info[:order] |
|
| 15 |
+ end |
|
| 16 |
+ |
|
| 17 |
+ def set_table_sort(sort_options) |
|
| 18 |
+ valid_sorts = sort_options[:sorts] || raise("You must specify :sorts as an array of valid sort attributes.")
|
|
| 19 |
+ default = sort_options[:default] || { valid_sorts.first.to_sym => :desc }
|
|
| 20 |
+ |
|
| 21 |
+ if params[:sort].present? |
|
| 22 |
+ attribute, direction = params[:sort].downcase.split('.')
|
|
| 23 |
+ unless valid_sorts.include?(attribute) |
|
| 24 |
+ attribute, direction = default.to_a.first |
|
| 25 |
+ end |
|
| 26 |
+ else |
|
| 27 |
+ attribute, direction = default.to_a.first |
|
| 28 |
+ end |
|
| 29 |
+ |
|
| 30 |
+ direction = direction.to_s == 'desc' ? 'desc' : 'asc' |
|
| 31 |
+ |
|
| 32 |
+ @table_sort_info = {
|
|
| 33 |
+ order: { attribute.to_sym => direction.to_sym },
|
|
| 34 |
+ attribute: attribute, |
|
| 35 |
+ direction: direction |
|
| 36 |
+ } |
|
| 37 |
+ end |
|
| 38 |
+ |
|
| 39 |
+ module SortableTableHelper |
|
| 40 |
+ def sortable_column(attribute, name = attribute.humanize, default_direction = 'desc') |
|
| 41 |
+ selected = @table_sort_info[:attribute].to_s == attribute |
|
| 42 |
+ if selected |
|
| 43 |
+ direction = @table_sort_info[:direction] |
|
| 44 |
+ new_direction = direction.to_s == 'desc' ? 'asc' : 'desc' |
|
| 45 |
+ classes = "selected #{direction}"
|
|
| 46 |
+ else |
|
| 47 |
+ classes = '' |
|
| 48 |
+ new_direction = default_direction |
|
| 49 |
+ end |
|
| 50 |
+ link_to(name, url_for(sort: "#{attribute}.#{new_direction}"), class: classes)
|
|
| 51 |
+ end |
|
| 52 |
+ end |
|
| 53 |
+end |
@@ -1,8 +1,11 @@ |
||
| 1 | 1 |
class ScenariosController < ApplicationController |
| 2 |
+ include SortableTable |
|
| 2 | 3 |
skip_before_filter :authenticate_user!, :only => :export |
| 3 | 4 |
|
| 4 | 5 |
def index |
| 5 |
- @scenarios = current_user.scenarios.page(params[:page]) |
|
| 6 |
+ set_table_sort sorts: %w[name public], default: { name: :asc }
|
|
| 7 |
+ |
|
| 8 |
+ @scenarios = current_user.scenarios.reorder(table_sort).page(params[:page]) |
|
| 6 | 9 |
|
| 7 | 10 |
respond_to do |format| |
| 8 | 11 |
format.html |
@@ -21,7 +24,9 @@ class ScenariosController < ApplicationController |
||
| 21 | 24 |
|
| 22 | 25 |
def show |
| 23 | 26 |
@scenario = current_user.scenarios.find(params[:id]) |
| 24 |
- @agents = @scenario.agents.preload(:scenarios).page(params[:page]) |
|
| 27 |
+ |
|
| 28 |
+ set_table_sort sorts: %w[name last_check_at last_event_at last_receive_at], default: { name: :asc }
|
|
| 29 |
+ @agents = @scenario.agents.preload(:scenarios, :controllers).reorder(table_sort).page(params[:page]) |
|
| 25 | 30 |
|
| 26 | 31 |
respond_to do |format| |
| 27 | 32 |
format.html |
@@ -1,8 +1,12 @@ |
||
| 1 | 1 |
class ServicesController < ApplicationController |
| 2 |
+ include SortableTable |
|
| 3 |
+ |
|
| 2 | 4 |
before_filter :upgrade_warning, only: :index |
| 3 | 5 |
|
| 4 | 6 |
def index |
| 5 |
- @services = current_user.services.page(params[:page]) |
|
| 7 |
+ set_table_sort sorts: %w[provider name global], default: { provider: :asc }
|
|
| 8 |
+ |
|
| 9 |
+ @services = current_user.services.reorder(table_sort).page(params[:page]) |
|
| 6 | 10 |
|
| 7 | 11 |
respond_to do |format| |
| 8 | 12 |
format.html |
@@ -1,6 +1,10 @@ |
||
| 1 | 1 |
class UserCredentialsController < ApplicationController |
| 2 |
+ include SortableTable |
|
| 3 |
+ |
|
| 2 | 4 |
def index |
| 3 |
- @user_credentials = current_user.user_credentials.page(params[:page]) |
|
| 5 |
+ set_table_sort sorts: %w[credential_name credential_value], default: { credential_name: :asc }
|
|
| 6 |
+ |
|
| 7 |
+ @user_credentials = current_user.user_credentials.reorder(table_sort).page(params[:page]) |
|
| 4 | 8 |
|
| 5 | 9 |
respond_to do |format| |
| 6 | 10 |
format.html |
@@ -31,7 +31,7 @@ module AgentHelper |
||
| 31 | 31 |
end |
| 32 | 32 |
|
| 33 | 33 |
def agent_controllers(agent, delimiter = ', ') |
| 34 |
- unless agent.controllers.empty? |
|
| 34 |
+ if agent.controllers.present? |
|
| 35 | 35 |
agent.controllers.map { |agent|
|
| 36 | 36 |
link_to(agent.name, agent_path(agent)) |
| 37 | 37 |
}.join(delimiter).html_safe |
@@ -1,11 +1,11 @@ |
||
| 1 | 1 |
<div class='table-responsive'> |
| 2 | 2 |
<table class='table table-striped'> |
| 3 | 3 |
<tr> |
| 4 |
- <th>Name</th> |
|
| 4 |
+ <th><%= sortable_column 'name', 'Name', 'asc' %></th> |
|
| 5 | 5 |
<th>Schedule</th> |
| 6 |
- <th>Last Check</th> |
|
| 7 |
- <th>Last Event Out</th> |
|
| 8 |
- <th>Last Event In</th> |
|
| 6 |
+ <th><%= sortable_column 'last_check_at', 'Last Check' %></th> |
|
| 7 |
+ <th><%= sortable_column 'last_event_at', 'Last Event Out' %></th> |
|
| 8 |
+ <th><%= sortable_column 'last_receive_at', 'Last Event In' %></th> |
|
| 9 | 9 |
<th>Events Created</th> |
| 10 | 10 |
<th>Working?</th> |
| 11 | 11 |
<th></th> |
@@ -12,9 +12,9 @@ |
||
| 12 | 12 |
|
| 13 | 13 |
<table class='table table-striped'> |
| 14 | 14 |
<tr> |
| 15 |
- <th>Name</th> |
|
| 15 |
+ <th><%= sortable_column 'name', 'Name', 'asc' %></th> |
|
| 16 | 16 |
<th>Agents</th> |
| 17 |
- <th>Public</th> |
|
| 17 |
+ <th><%= sortable_column 'public' %></th> |
|
| 18 | 18 |
<th></th> |
| 19 | 19 |
</tr> |
| 20 | 20 |
|
@@ -25,9 +25,9 @@ |
||
| 25 | 25 |
<div class='table-responsive'> |
| 26 | 26 |
<table class='table table-striped events'> |
| 27 | 27 |
<tr> |
| 28 |
- <th>Provider</th> |
|
| 29 |
- <th>Username</th> |
|
| 30 |
- <th>Global?</th> |
|
| 28 |
+ <th><%= sortable_column 'provider', 'Provider', 'asc' %></th> |
|
| 29 |
+ <th><%= sortable_column 'name', 'Name', 'asc' %></th> |
|
| 30 |
+ <th><%= sortable_column 'global', 'Global?' %></th> |
|
| 31 | 31 |
<th></th> |
| 32 | 32 |
</tr> |
| 33 | 33 |
|
@@ -14,8 +14,8 @@ |
||
| 14 | 14 |
|
| 15 | 15 |
<table class='table table-striped'> |
| 16 | 16 |
<tr> |
| 17 |
- <th>Name</th> |
|
| 18 |
- <th>Value</th> |
|
| 17 |
+ <th><%= sortable_column 'credential_name', 'Name', 'asc' %></th> |
|
| 18 |
+ <th><%= sortable_column 'credential_value', 'Value', 'asc' %></th> |
|
| 19 | 19 |
</tr> |
| 20 | 20 |
|
| 21 | 21 |
<% @user_credentials.each do |user_credential| %> |
@@ -0,0 +1,61 @@ |
||
| 1 |
+require 'spec_helper' |
|
| 2 |
+ |
|
| 3 |
+describe SortableTable do |
|
| 4 |
+ class SortableTestController |
|
| 5 |
+ attr_accessor :params |
|
| 6 |
+ |
|
| 7 |
+ def self.helper(foo) |
|
| 8 |
+ end |
|
| 9 |
+ |
|
| 10 |
+ include SortableTable |
|
| 11 |
+ |
|
| 12 |
+ public :set_table_sort |
|
| 13 |
+ public :table_sort |
|
| 14 |
+ end |
|
| 15 |
+ |
|
| 16 |
+ describe "#set_table_sort" do |
|
| 17 |
+ let(:controller) { SortableTestController.new }
|
|
| 18 |
+ let(:default) { { column2: :asc }}
|
|
| 19 |
+ let(:options) { { sorts: %w[column1 column2], default: default } }
|
|
| 20 |
+ |
|
| 21 |
+ it "uses a default when no sort is given" do |
|
| 22 |
+ controller.params = {}
|
|
| 23 |
+ controller.set_table_sort options |
|
| 24 |
+ controller.table_sort.should == default |
|
| 25 |
+ end |
|
| 26 |
+ |
|
| 27 |
+ it "applies the given sort when one is passed in" do |
|
| 28 |
+ controller.params = { sort: "column1.desc" }
|
|
| 29 |
+ controller.set_table_sort options |
|
| 30 |
+ controller.table_sort.should == { column1: :desc }
|
|
| 31 |
+ |
|
| 32 |
+ controller.params = { sort: "column1.asc" }
|
|
| 33 |
+ controller.set_table_sort options |
|
| 34 |
+ controller.table_sort.should == { column1: :asc }
|
|
| 35 |
+ |
|
| 36 |
+ controller.params = { sort: "column2.desc" }
|
|
| 37 |
+ controller.set_table_sort options |
|
| 38 |
+ controller.table_sort.should == { column2: :desc }
|
|
| 39 |
+ end |
|
| 40 |
+ |
|
| 41 |
+ it "ignores unknown directions" do |
|
| 42 |
+ controller.params = { sort: "column1.foo" }
|
|
| 43 |
+ controller.set_table_sort options |
|
| 44 |
+ controller.table_sort.should == { column1: :asc }
|
|
| 45 |
+ |
|
| 46 |
+ controller.params = { sort: "column1.foo drop tables" }
|
|
| 47 |
+ controller.set_table_sort options |
|
| 48 |
+ controller.table_sort.should == { column1: :asc }
|
|
| 49 |
+ end |
|
| 50 |
+ |
|
| 51 |
+ it "ignores unknown columns" do |
|
| 52 |
+ controller.params = { sort: "foo.asc" }
|
|
| 53 |
+ controller.set_table_sort options |
|
| 54 |
+ controller.table_sort.should == default |
|
| 55 |
+ |
|
| 56 |
+ controller.params = { sort: ";drop table;.asc" }
|
|
| 57 |
+ controller.set_table_sort options |
|
| 58 |
+ controller.table_sort.should == default |
|
| 59 |
+ end |
|
| 60 |
+ end |
|
| 61 |
+end |
@@ -55,6 +55,8 @@ RSpec.configure do |config| |
||
| 55 | 55 |
config.global_fixtures = :all |
| 56 | 56 |
config.treat_symbols_as_metadata_keys_with_true_values = true |
| 57 | 57 |
|
| 58 |
+ config.render_views |
|
| 59 |
+ |
|
| 58 | 60 |
config.include Devise::TestHelpers, :type => :controller |
| 59 | 61 |
config.include SpecHelpers |
| 60 | 62 |
config.include Delorean |